package com.scfinance.SPD.encrypt;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import javax.crypto.SecretKey;

import org.apache.commons.logging.Log;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.scfinance.SPD.encrypt.util.*;

public class DataEncrypt {

	private static final String TAG = "DataEncrypt";
	public static final String UNENCRYPTION = "0";// 非加密
	public static final String ENCRYPTION = "1";// 加密

	public static DataEncrypt initialized(){ return new DataEncrypt(); }

	/**
	 * 数据加密
	 * 
	 * @param reqMethod
	 *            请求接口方法名
	 * @param reqContent
	 *            请求参数、
	 * @param type 
	 * 			是否加密方式1：加密，0：不加密
	 * @return
	 */
	public String encrypt(String reqMethod, JSONObject reqContent, String type) {

		String result = null;
		String randomkey = CryptUtil.generate24RandomString();
		String versionName = "2.5";
		try {
			// 生成头部分
			JSONObject headJson = new JSONObject();
			headJson.put("version", versionName);
			headJson.put("kid", "1");
			headJson.put("code", "00");
			headJson.put("deskey", randomkey);
			headJson.put("encrypt", type);
			// body sysreq对象 中 sign--md5报文内容体摘要
			// 数据进行排序
			List<JSONOrder> list = new ArrayList<JSONOrder>();
			for (Iterator<String> iterator = reqContent.keySet().iterator(); iterator
					.hasNext();) {
				JSONOrder jsonOrder = new JSONOrder();
				String key = iterator.next();
				if (reqContent.get(key) instanceof JSONArray) {
					continue;
				}
				jsonOrder.setKey(key);
				jsonOrder.setValue(reqContent.getString(key));
				list.add(jsonOrder);
			}

			Collections.sort(list, new Comparator<JSONOrder>() {// 排序
						@Override
						public int compare(JSONOrder currentJson,
								JSONOrder nextJson) {
							return nextJson.getKey().compareTo(
									currentJson.getKey());
						}
					});
			// 结束排序

			// 获取值
			StringBuilder contentSb = new StringBuilder();
			for (JSONOrder jsonOrder : list) {
				contentSb.append(jsonOrder.getValue());
			}

			String sign = MD5.encrypt(contentSb.toString()
					+ MD5.encrypt(ConstantUtil.encryptKey));

			JSONObject sysreqJson = new JSONObject();
			sysreqJson.put("encrypt", "1");
			sysreqJson.put("method", reqMethod);
			sysreqJson.put("sessionkey", "");
			sysreqJson.put("v", "1.0");
			sysreqJson.put("sig", sign);
			sysreqJson.put("timestamp", CryptUtil.getTimestamp());

			// 组装body内容
			SecretKey deskey = CryptUtil.genDESKey(randomkey);
			JSONObject bodyJson = reqContent;
			bodyJson.put("sysreq", sysreqJson);
			// body 的3des加密
			String body = CryptUtil.desEncrypt(deskey,
					URLEncoder.encode(bodyJson.toString(), "UTF-8"));
			// 对head进行RSA加密
			String head = "";
			if (ConstantUtil.ENCRYPTSTATUS == Constant.RSA) {
				head = RSAEncrypt.encryptKey(headJson.toString(),
						RSAUtil.getPublickey(), RSAUtil.getModule());// 软加密的处理方式
			} else {
				head = RSAUtil.encryptKey(headJson.toString()); // ut环境专用
			}
			// 得到一个整体的Json数据流字符串
			JSONObject requestJson = new JSONObject();
			requestJson.put("head", head);
			requestJson.put("body", body);
			result = requestJson.toString();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
		System.out.println(result);
		return result;
	}

	/**
	 * 数据解密
	 * 
	 * @param str
	 *            加密数据
	 * @return
	 */
	public String deEncrypt(String str) {
		String result = "";
		try {
			// 解析请求消息
			JSONObject jsonObject = JSONObject.parseObject(str);
			String head = jsonObject.getString("head");
			String body = jsonObject.getString("body");
			// RSA解密
			if (ConstantUtil.ENCRYPTSTATUS == Constant.RSA) {
				head = RSAEncrypt.decryptKey(head, RSAUtil.getPublickey(),
						RSAUtil.getModule());// 软加密的处理情况
			} else {
				head = RSAUtil.decryptKey(head);// ut环境专用
			}
			// 3DES解密
			JSONObject headJson = JSONObject.parseObject(head);
			String desKey = headJson.getString("deskey");
			String encrypt = headJson.getString("encrypt");
			// 头部分抛出异常
			if (!"00".equals(headJson.getString("code"))) {
				System.out.println("客户端数字签名异常");
				return "";
			}
			// 判断是否加密
			if (encrypt != null && encrypt.equals(UNENCRYPTION)) {
				return body;
			}
			SecretKey secretKey = CryptUtil.genDESKey(desKey);
			body = URLDecoder.decode(CryptUtil.desDecrypt(secretKey, body),
					"UTF-8");
			// 体部分抛出异常
			JSONObject bodyJo = JSONObject.parseObject(body);
			JSONObject resJo = bodyJo.getJSONObject("sysres");
			// 请求体抛出的异常信息
			String errorCode = resJo.getString("errorCode");
			Constant.ERRORCODE = errorCode; // 便于根据错误码处理业务逻辑
			Constant.ERRORMSG = resJo.getString("errorMsg");
			// 获取响应头的签名信息
			String sign = resJo.getString("sig");
			// body sysreq对象 中 sign--md5报文内容体摘要
			boolean isEnterKey = true;
			// 进行排序
			List<JSONOrder> list = new ArrayList<JSONOrder>();
			for (Iterator<String> iterator = bodyJo.keySet().iterator(); iterator.hasNext();) {
				JSONOrder jsonOrder = new JSONOrder();
				String key = iterator.next();
				if (key.equalsIgnoreCase("rclist")) {
					isEnterKey = false;
					break;
				}
				if (key.equalsIgnoreCase("sysres"))
					continue;
				jsonOrder.setKey(key);
				jsonOrder.setValue(bodyJo.getString(key));
				list.add(jsonOrder);
			}
			String generationSign = "";
			if (isEnterKey) {
				Collections.sort(list, new Comparator<JSONOrder>() {// 排序
							@Override
							public int compare(JSONOrder currentJson,
									JSONOrder nextJson) {
								return nextJson.getKey().compareTo(
										currentJson.getKey());
							}
						});
				// 结束排序
				StringBuilder contentSb = new StringBuilder();
				for (JSONOrder jsonOrder : list) {// 获取值
					contentSb.append(jsonOrder.getValue());
				}
				generationSign = MD5.encrypt(contentSb.toString()
						+ MD5.encrypt(ConstantUtil.encryptKey));// 返回是JSONObject
			} else {
				generationSign = MD5.encrypt(MD5
						.encrypt(ConstantUtil.encryptKey));// 返回的是JSONArray
			}
			// 签名内容比较
			if (!sign.equals(generationSign)) {
				System.out.println("服务端数字签名异常：sign=" + sign + "\n newSign="
						+ generationSign);
				return "";
			} else {
				// bodyJo.remove("sysres");
				result = bodyJo.toString();
			}
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

	/**
	 * 类名称：JSONOrder 类描述：json 排序对象
	 */
	private class JSONOrder {
		private String key;
		private String value;

		public String getKey() {
			return key;
		}

		public void setKey(String key) {
			this.key = key;
		}

		public String getValue() {
			return value;
		}

		public void setValue(String value) {
			this.value = value;
		}
	}
}
